-
Notifications
You must be signed in to change notification settings - Fork 323
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
modify key event logic to fix ctrl+space not being sent #569
modify key event logic to fix ctrl+space not being sent #569
Conversation
tgauth
commented
Feb 23, 2022
•
edited
Loading
edited
- address Control+Space not sent to terminal emulator Win32-OpenSSH#1842
- modifies key event logic based on https://github.com/microsoft/terminal/blob/main/src/cascadia/TerminalAzBridge/ConsoleInputReader.cpp
contrib/win32/win32compat/tncon.c
Outdated
if (inputRecord.Event.KeyEvent.uChar.UnicodeChar != L'\0') { | ||
// Ctrl+Space & Ctrl+@ generate a NULL character but should still be sent | ||
DWORD dwControlKeyState = inputRecord.Event.KeyEvent.dwControlKeyState; | ||
DWORD dwCtrlPressed = (dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only thing I'm concerned about is the !IsAltPressed()
check from the terminal side. Presumably that was there for a reason. @zadjii-msft? Do you recall?
My theory is that it had something to do with AltGr as that can be simulated with a Ctrl and an Alt (https://devblogs.microsoft.com/oldnewthing/20040329-00/?p=40003#:~:text=The%20combination%20Ctrl%2BAlt%20is%20also%20known%20as%20AltGr%2C,keyboards%20there%20are%20only%20two%20%28Normal%20and%20Shift%29.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(@lhecker might also know as he was in AltGr land for a while)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The change appears to be correct regarding AltGr from what I can tell.
The code that is relevant here are these two places:
- https://github.com/microsoft/terminal/blob/9ab4abfb5471e91235e34379bf90e24ec3a22c67/src/terminal/input/terminalInput.cpp#L558-L562
- https://github.com/microsoft/terminal/blob/9ab4abfb5471e91235e34379bf90e24ec3a22c67/src/terminal/input/terminalInput.cpp#L594-L601
- https://github.com/microsoft/terminal/blob/9ab4abfb5471e91235e34379bf90e24ec3a22c67/src/terminal/input/terminalInput.cpp#L635-L642
I added quite some extensive documentation to that function in the past and maybe it could be helpful here.
While we do have some special AltGr handling (first link) I don't think we'd ever send a client application a null-character for a AltGr sequence, so we don't need to check for that here.
I'm pretty sure that this change doesn't work for Ctrl+Space since it only checks for VkKeyScanW(0)
.
Additionally when it comes to terminals Ctrl+Alt+@ (but not AltGr+@!) should emit "\x1b[\0"
and not "\0"
.
Basically - according to what I know - Ctrl+2 is just a helper-shortcut in Terminals for Ctrl+@. The proper key-sequence is Ctrl+Shift+2. Back in the dark ages, the Ctrl key used to be a physical (electrical) mask-key which cleared the upper 2 bits of the 7 bit ASCII charset. Since @ is 0b1000000, Ctrl+@ is turned into 0b0000000 - a null byte.
But that means that the meaning of the Alt key is still true: Alt keys induce an escape sequence. Alt+Q is "\x1b[q"
and Ctrl+Alt+Shift+2 is "\x1b[\0"
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be more specific, I believe a solution might look like this (includes Ctrl+Space support):
// Returns true if this is a Ctrl+Space or Ctrl+@ combination.
// It assumes that inputRecord->Event.KeyEvent.uChar.UnicodeChar is 0.
static bool
IsNullKeySequence(const INPUT_RECORD* inputRecord)
{
DWORD state = inputRecord->Event.KeyEvent.dwControlKeyState;
WORD code = inputRecord->Event.KeyEvent.wVirtualKeyCode;
return (state & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
&& (code == LOBYTE(VkKeyScanW(0)) || code == LOBYTE(VkKeyScanW(L' ')));
}
And then use it as:
if (inputRecord.Event.KeyEvent.uChar.UnicodeChar != L'\0' || IsNullKeySequence(&inputRecord)) {
- I'm abusing C's support for "short-circuit evaluation"
By putting function calls into the right-hand-side of boolean conditions we can make sure that they're only called if the other side isn't already "satisfied". Basically with this in place,IsNullKeySequence
will only be called ifUnicodeChar
is actually 0. - I'm passing
INPUT_RECORD
by pointer ("by reference" in other languages), so that we don't incur a copy.GetVTSeqFromKeyStroke
should do the same. static
because the function is local to this file- If this code doesn't compile because of the "bool", replace it with
_Bool
, which is an official alias and will always work.
This code still doesn't support proper Alt handling, but I'm not sure how important that is for an initial bug fix. The previous code seemingly doesn't support it either after all. 🙂 TIL: In VT mode we send the VT sequences character by character in INPUT_RECORD
s, so Ctrl+Alt+@ will not result in a singular null byte anyways.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahhh, got it. Thanks for the detailed response!
This is a great fix with significant usability consequences, and I am looking forward to the new release. What is the process for getting this fix into an instance of Windows 11 so that Windows Terminal and ssh will work with CTRL+SPACE? Is there a public status board that shows the flow from GitHub to Windows? |
@donpellegrino - we don't have a status board, unfortunately. We typically wait a bit to receive feedback on a GitHub release before introducing it as a Windows release. There are also Windows schedules that we have to follow. For these reasons, 8.9 is not yet available as a Windows feature-on-demand. If you would like to use the 8.9.1.0 GitHub release on Windows 11, it is available to download with install instructions here. |
@tgauth - I has been about one year since your patch. Using a fully up-to-date Windows 11 Pro 22H2 (OS build 22621.1194) as of today, February 13, 2023, I still see:
I would love to see your work make it through to the production release. |
@donpellegrino yes, this change will be in the next Windows release (23H2) - https://learn.microsoft.com/en-us/windows/release-health/release-information OpenSSH 8.9 is currently shipping with Windows Insider Builds. |
Win11 23H2 still does not have this fix |